/*
PearReview - The peer review assistant.
Copyright (C) 2009  Dimitrij Pankratz, Anton Musichin
http://www.pearreview.com, info@pearreview.com

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package com.pearreview.util.review.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Stack;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.Duration;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import com.pearreview.util.review.*;


public class XMLReviewReader implements ReviewReader {

	private static final long serialVersionUID = -4679619923186403847L;
	
	private enum Elements {
		REVIEW,
		
		REVIEW_NAME,
		
		REVIEW_DESCRIPTION,
		
		REVIEW_PRODUCT,
		REVIEW_PRODUCT_NAME,
		REVIEW_PRODUCT_REFERENCE,
		REVIEW_PRODUCT_VERSION,
		
		REVIEW_ATTENDEE,
		REVIEW_ATTENDEE_ID,
		REVIEW_ATTENDEE_NAME,
		REVIEW_ATTENDEE_CONTACT,
		REVIEW_ATTENDEE_ROLE,
		REVIEW_ATTENDEE_ASPECTS,
		REVIEW_ATTENDEE_ASPECTS_ASPECT$ID,
		
		REVIEW_ASPECT,
		REVIEW_ASPECT_ID,
		REVIEW_ASPECT_CATEGORY,
		REVIEW_ASPECT_DIRECTIVE,
		REVIEW_ASPECT_DESCRIPTION,
		
		REVIEW_SEVERETIES,
		REVIEW_SEVERETIES_SEVERITY,
		
		REVIEW_MEETING,
		REVIEW_MEETING_PLANNED$DATE,
		REVIEW_MEETING_PLANNED$START,
		REVIEW_MEETING_PLANNED$END,
		REVIEW_MEETING_PLANNED$LOCATION,
		REVIEW_MEETING_PROTOCOL,
		REVIEW_MEETING_CANCELED,
		REVIEW_MEETING_COMMENTS,
		REVIEW_MEETING_PROTOCOL_DATE,
		REVIEW_MEETING_PROTOCOL_START,
		REVIEW_MEETING_PROTOCOL_END,
		REVIEW_MEETING_PROTOCOL_LOCATION,
		REVIEW_MEETING_PROTOCOL_ATTENDEE,
		REVIEW_MEETING_PROTOCOL_FINDING,
		REVIEW_MEETING_PROTOCOL_COMMENTS,
		REVIEW_MEETING_PROTOCOL_ATTENDEE_ATTENDEE,
		REVIEW_MEETING_PROTOCOL_ATTENDEE_PREPARATION$TIME,
		REVIEW_MEETING_PROTOCOL_FINDING_ID,
		REVIEW_MEETING_PROTOCOL_FINDING_SEVERITY,
		REVIEW_MEETING_PROTOCOL_FINDING_DESCRIPTION,
		REVIEW_MEETING_PROTOCOL_FINDING_REFERENCE,
		REVIEW_MEETING_PROTOCOL_FINDING_EXTERNAL$REFERENCE,
		REVIEW_MEETING_PROTOCOL_FINDING_ASPECT,
		
		REVIEW_IMPRESSION,
		
		REVIEW_RECOMMENDATION,
		
		REVIEW_COMMENTS,
	}
	
	/**
	 * Class constructor. Default XML schema file will be used.
	 */
	public XMLReviewReader() {
	}

	@Override
	public Review read(File file) throws SAXException, IOException, 
			NotValidXMLException, ParserConfigurationException,
			DatatypeConfigurationException {
		
		XMLSchemaValidator validator = new XMLSchemaValidator();
		
			
		//throw an exception if file is not valid
		if (!validator.validate(file)) {
			throw new NotValidXMLException(validator.getLastErrorMessage());
		}
		
		XMLReviewSaxReader reader = new XMLReviewSaxReader();
		InputStream fileStream = new FileInputStream(file);
		Review review = reader.read(fileStream);
		
		//check references of products, if no reference is in list => at least
		//one reference was an empty string.
		if (review.getProduct().getReference().size() == 0) {
			review.getProduct().getReference().add("");
		}
		
		
		review = connectWithIds(review);
		
		return review;
	}
	
	/**
	 * Connects id internal id references with the objects.
	 * 
	 * @param review
	 * @return
	 */
	protected Review connectWithIds(Review review) {
		IdList<Attendee> reviewAttendeesList = review.getAttendees();
		IdList<Aspect> reviewAspectsList = review.getAspects();
		
		//connect the ids of the attendee aspects with real aspects
		for (Attendee attendee : reviewAttendeesList) {
			IdList<Aspect> attendeeAspects = attendee.getAspects();
			IdList<Aspect> newAttendeeAspects = new IdArrayList<Aspect>();
			if (attendeeAspects != null) {
				for (Aspect aspect : attendeeAspects) {
					if (reviewAspectsList.hasId(aspect.getId())) {
						IdList<Aspect> temp = 
							reviewAspectsList.getWithId(aspect.getId());
						if (temp.size() == 1) {
							newAttendeeAspects.add(temp.get(0));
						} else {
							//TODO throw new Exception();
						}
					} else {
						//TODO throw new Exception();
					}
					attendee.setAspects(newAttendeeAspects);
				}
			}
		}
		review.setAttendees(reviewAttendeesList);
		
		List<Meeting> reviewMeetings = review.getMeetings();
		
		//connect available attendee ids with real attendees
		for (Meeting meeting : reviewMeetings) {
			Protocol protocol = meeting.getProtocol();
			
			if (protocol != null) {
				
				IdList<AvailableAttendee> reviewProtocolAttendees 
					= protocol.getAvailableAttendees();
				for (AvailableAttendee attendee : reviewProtocolAttendees) {
					if (reviewAttendeesList.hasId(attendee.getId())) {
						IdList<Attendee> temp = 
							reviewAttendeesList.getWithId(attendee.getId());
						if (temp.size() == 1) {
							attendee.setAttendee(temp.get(0));
						} else {
							//TODO throw new Exception();
							/*
							attendee.setName(temp.get(0).getName());
							attendee.setContact(temp.get(0).getContact());
							attendee.setRole(temp.get(0).getRole());
							attendee.setAspects(temp.get(0).getAspects());
							*/
						} 
					} else {
						//TODO throw new Exception();
					}
				}
			}
		}
		
		//connect severities from findings with findings from review
		for (Meeting meeting : reviewMeetings) {
			Protocol protocol = meeting.getProtocol();
			
			if (protocol != null) {
				
				IdList<Finding> reviewProtocolFindings
					= protocol.getFindings();
				for (Finding finding : reviewProtocolFindings) {
					for (Severity severity: review.getSeverities()) {
						if (finding.getSeverity().getName().equals(
								severity.getName())) {
							finding.setSeverity(severity);
							continue;
						}
					}
				}
			}
		}
		
		return review;
	}
	
	private class XMLReviewSaxReader extends DefaultHandler 
			implements Serializable {
		private static final long serialVersionUID = 6229090893464384111L;
		
		protected Stack<String> depth = new Stack<String>();
		protected SAXParser parser;
		protected Elements currentElement;
		protected int currentElementState;
		protected Review review;
		protected final int CLOSED = 1;
		protected final int OPENED = 2;
		
		protected List<String> reviewProductReference = new ArrayList<String>();
		protected IdList<Attendee> reviewAttendees = new IdArrayList<Attendee>();
		protected Attendee currentAttendee; 
		protected IdList<Aspect> reviewAttendeesAspects;
		protected IdList<Aspect> reviewAspects = new IdArrayList<Aspect>();
		protected Aspect currentAspect;
		protected List<Severity> reviewSeverities = new ArrayList<Severity>();
		protected Meeting currentMeeting;
		protected List<Meeting> reviewMeetings = new ArrayList<Meeting>();
		protected Protocol currentProtocol = null;
		protected IdList<Finding> reviewMeetingProtocolFindings = null;
		protected Finding currentFinding;
		protected List<String> reviewMeetingProtocolFindingReferences = null;
		protected List<String> reviewMeetingProtocolFindingExternalReferences = null;
		protected List<String> reviewMeetingProtocolFindingAspects = null;
		protected AvailableAttendee currentAvailableAttendee = null;
		protected IdList<AvailableAttendee> availableAttendees = null;
		
		protected DatatypeFactory dataType;
		
		
		/**
		 * Class constructor.
		 * @throws SAXException 
		 * @throws ParserConfigurationException 
		 * 
		 * @throws SAXException
		 * @throws ParserConfigurationException
		 * @throws DatatypeConfigurationException 
		 */
		public XMLReviewSaxReader() throws ParserConfigurationException, 
				SAXException, DatatypeConfigurationException {
			//Instantiate the parser
			SAXParserFactory fac = SAXParserFactory.newInstance();
			parser = fac.newSAXParser();
			
			dataType = DatatypeFactory.newInstance();
		}
		
		/**
		 * Reads the given file and parses the XML structure into the review
		 * structure.
		 * 
		 * @param file File to parse.
		 * @return Wine cellar structure filled with parsed data.
		 * @throws SAXException
		 * @throws IOException
		 */
		public Review read(InputStream file) throws SAXException, IOException {
			//parse document
			parser.parse(file, this);
			return review;
		}
				
		@Override
		public void startDocument() {
			//depth = new Stack<String>();
		}
		
		
		public void startElement(String url, String localName, String qName,
				Attributes attributes) throws SAXException {

			String[] split = qName.split(":");
			//name without namespace attribute 
			String name = split[split.length-1];
			depth.push(name);
			currentElementState = OPENED;
			
			if (name.equals ("review")) {
				currentElement = Elements.REVIEW;
				review = new Review();
			} else if (name.equals("name") && depth.get(1).equals ("name") && depth.size() == 2) {
				currentElement = Elements.REVIEW_NAME;
				review.setName("");
			} else if (name.equals ("description") && depth.get(1).equals ("description") && depth.size() == 2) {
				currentElement = Elements.REVIEW_DESCRIPTION;
				review.setDescription("");
			} else if (name.equals ("product")) {
				currentElement = Elements.REVIEW_PRODUCT;
				review.setProduct(new Product());
			} else if (name.equals ("name") && depth.get(1).equals ("product")) {
				currentElement = Elements.REVIEW_PRODUCT_NAME;
				review.getProduct().setName("");
			} else if (name.equals ("reference") && depth.get(1).equals ("product")) {
				currentElement = Elements.REVIEW_PRODUCT_REFERENCE;
			} else if (name.equals ("version") && depth.get(1).equals ("product")) {
				currentElement = Elements.REVIEW_PRODUCT_VERSION;
				review.getProduct().setVersion("");
			} else if (name.equals ("attendee") && depth.get(1).equals ("attendee")) {
				currentElement = Elements.REVIEW_ATTENDEE;
				currentAttendee = new Attendee();
			} else if (name.equals ("id") && depth.get(1).equals ("attendee")) {
				currentElement = Elements.REVIEW_ATTENDEE_ID;
				currentAttendee.setId("");
			} else if (name.equals ("name") && depth.get(1).equals ("attendee")) {
				currentElement = Elements.REVIEW_ATTENDEE_NAME;
				currentAttendee.setName("");
			} else if (name.equals ("contact") && depth.get(1).equals ("attendee")) {
				currentElement = Elements.REVIEW_ATTENDEE_CONTACT;
				currentAttendee.setContact("");
			} else if (name.equals ("role") && depth.get(1).equals ("attendee")) {
				currentElement = Elements.REVIEW_ATTENDEE_ROLE;
			} else if (name.equals ("aspects") && depth.get(1).equals ("attendee")) {
				currentElement = Elements.REVIEW_ATTENDEE_ASPECTS;
				reviewAttendeesAspects = new IdArrayList<Aspect>();
			} else if (name.equals ("aspect-id") && depth.get(1).equals ("attendee")) {
				currentElement = Elements.REVIEW_ATTENDEE_ASPECTS_ASPECT$ID;
			} else if (name.equals ("aspect") && depth.get(1).equals ("aspect")) {
				currentElement = Elements.REVIEW_ASPECT;
				currentAspect = new Aspect();
			} else if (name.equals ("id") && depth.get(1).equals ("aspect")) {
				currentElement = Elements.REVIEW_ASPECT_ID;
				currentAspect.setId("");
			} else if (name.equals ("category") && depth.get(1).equals ("aspect")) {
				currentElement = Elements.REVIEW_ASPECT_CATEGORY;
				currentAspect.setCategory("");
			} else if (name.equals ("directive") && depth.get(1).equals ("aspect")) {
				currentElement = Elements.REVIEW_ASPECT_DIRECTIVE;
				currentAspect.setDirective("");
			} else if (name.equals ("description") && depth.get(1).equals ("aspect")) {
				currentElement = Elements.REVIEW_ASPECT_DESCRIPTION;
				currentAspect.setDescription("");
			} else if (name.equals ("severities") && depth.get(1).equals ("severities")) {
				currentElement = Elements.REVIEW_SEVERETIES;
			} else if (name.equals ("severity") && depth.get(1).equals ("severities")) {
				currentElement = Elements.REVIEW_SEVERETIES_SEVERITY;
			} else if (name.equals ("meeting") && depth.get(1).equals ("meeting")) {
				currentElement = Elements.REVIEW_MEETING;
				currentMeeting = new Meeting();
			} else if (name.equals ("planned-date") && depth.get(1).equals ("meeting")) {
				currentElement = Elements.REVIEW_MEETING_PLANNED$DATE;
			} else if (name.equals ("planned-start") && depth.get(1).equals ("meeting")) {
				currentElement = Elements.REVIEW_MEETING_PLANNED$START;
			} else if (name.equals ("planned-end") && depth.get(1).equals ("meeting")) {
				currentElement = Elements.REVIEW_MEETING_PLANNED$END;
			} else if (name.equals ("planned-location") && depth.get(1).equals ("meeting")) {
				currentElement = Elements.REVIEW_MEETING_PLANNED$LOCATION;
				currentMeeting.setPlannedLocation("");
			} else if (name.equals ("protocol") && depth.get(1).equals ("meeting")) {
				currentElement = Elements.REVIEW_MEETING_PROTOCOL;
				currentProtocol = new Protocol();
				reviewMeetingProtocolFindings = new IdArrayList<Finding>();
				availableAttendees = new IdArrayList<AvailableAttendee>();
			} else if (name.equals ("date") && depth.get(1).equals ("meeting") && depth.get(2).equals ("protocol")) {
				currentElement = Elements.REVIEW_MEETING_PROTOCOL_DATE;
			} else if (name.equals ("start") && depth.get(1).equals ("meeting") && depth.get(2).equals ("protocol")) {
				currentElement = Elements.REVIEW_MEETING_PROTOCOL_START;
			} else if (name.equals ("end") && depth.get(1).equals ("meeting") && depth.get(2).equals ("protocol")) {
				currentElement = Elements.REVIEW_MEETING_PROTOCOL_END;
			} else if (name.equals ("location") && depth.get(1).equals ("meeting") && depth.get(2).equals ("protocol")) {
				currentElement = Elements.REVIEW_MEETING_PROTOCOL_LOCATION;
				currentProtocol.setLocation("");
			} else if (depth.size() == 5 && name.equals ("attendee") && depth.get(1).equals ("meeting") && depth.get(2).equals ("protocol") && depth.get(3).equals ("attendee") && depth.get(4).equals ("attendee")) {
				currentElement = Elements.REVIEW_MEETING_PROTOCOL_ATTENDEE_ATTENDEE;
				currentAvailableAttendee.setId("");
			} else if (name.equals ("attendee") && depth.get(1).equals ("meeting") && depth.get(2).equals ("protocol") && depth.size() == 4) {
				currentElement = Elements.REVIEW_MEETING_PROTOCOL_ATTENDEE;
				currentAvailableAttendee = new AvailableAttendee(new Attendee());
			} else if (name.equals ("preparation-time") && depth.get(1).equals ("meeting") && depth.get(2).equals ("protocol") && depth.get(3).equals ("attendee")) {
				currentElement = Elements.REVIEW_MEETING_PROTOCOL_ATTENDEE_PREPARATION$TIME;
			} else if (name.equals ("finding") && depth.get(1).equals ("meeting") && depth.get(2).equals ("protocol") && depth.get(3).equals ("finding")) {
				currentElement = Elements.REVIEW_MEETING_PROTOCOL_FINDING;
				currentFinding = new Finding();
				reviewMeetingProtocolFindingReferences = new ArrayList<String>();
				reviewMeetingProtocolFindingExternalReferences = new ArrayList<String>();
				reviewMeetingProtocolFindingAspects = new ArrayList<String>();
			} else if (name.equals ("id") && depth.get(1).equals ("meeting") && depth.get(2).equals ("protocol") && depth.get(3).equals ("finding")) {
				currentElement = Elements.REVIEW_MEETING_PROTOCOL_FINDING_ID;
				currentFinding.setId("");
			} else if (name.equals ("severity") && depth.get(1).equals ("meeting") && depth.get(2).equals ("protocol") && depth.get(3).equals ("finding")) {
				currentElement = Elements.REVIEW_MEETING_PROTOCOL_FINDING_SEVERITY;
				currentFinding.setSeverity(new Severity(""));
			} else if (name.equals ("description") && depth.get(1).equals ("meeting") && depth.get(2).equals ("protocol") && depth.get(3).equals ("finding")) {
				currentElement = Elements.REVIEW_MEETING_PROTOCOL_FINDING_DESCRIPTION;
				currentFinding.setDescription("");
			} else if (name.equals ("reference") && depth.get(1).equals ("meeting") && depth.get(2).equals ("protocol") && depth.get(3).equals ("finding")) {
				currentElement = Elements.REVIEW_MEETING_PROTOCOL_FINDING_REFERENCE;
			} else if (name.equals ("external-reference") && depth.get(1).equals ("meeting") && depth.get(2).equals ("protocol") && depth.get(3).equals ("finding")) {
				currentElement = Elements.REVIEW_MEETING_PROTOCOL_FINDING_EXTERNAL$REFERENCE;
			} else if (name.equals ("aspect") && depth.get(1).equals ("meeting") && depth.get(2).equals ("protocol") && depth.get(3).equals ("finding")) {
				currentElement = Elements.REVIEW_MEETING_PROTOCOL_FINDING_ASPECT;
			} else if (name.equals ("comments") && depth.get(1).equals ("meeting") && depth.get(2).equals ("protocol")) {
				currentElement = Elements.REVIEW_MEETING_PROTOCOL_COMMENTS;
				currentProtocol.setComments("");
			} else if (name.equals ("canceled") && depth.get(1).equals ("meeting")) {
				currentElement = Elements.REVIEW_MEETING_CANCELED;
				currentMeeting.setCanceled("");
			} else if (name.equals ("comments") && depth.get(1).equals ("meeting")) {
				currentElement = Elements.REVIEW_MEETING_COMMENTS;
				currentMeeting.setComments("");
			} else if (name.equals ("impression") && depth.get(1).equals ("impression")) {
				currentElement = Elements.REVIEW_IMPRESSION;
				review.setImpression("");
			} else if (name.equals ("recommendation") && depth.get(1).equals ("recommendation")) {
				currentElement = Elements.REVIEW_RECOMMENDATION;
				review.setRecommendation("");
			} else if (name.equals ("comments") && depth.get(1).equals ("comments")) {
				currentElement = Elements.REVIEW_COMMENTS;
				review.setComments("");
			}
		}
		
		public void endElement (String uri, String localName, String qName)
				throws SAXException {
			
			String[] split = qName.split(":");
			String name = split[split.length-1];
			
			if (name.equals ("review")) {
				review.setAttendees(reviewAttendees);
				review.setAspects(reviewAspects);
				review.setSeverities(reviewSeverities);
				review.setMeetings(reviewMeetings);
			}
			
			if (name.equals ("product") && depth.get(1).equals ("product") && depth.size() == 2) {
				review.getProduct().setReference(reviewProductReference);
			}
			
			if (name.equals ("aspects") && depth.get(1).equals ("attendee") && depth.get(2).equals ("aspects") && depth.size() == 3) {
				currentAttendee.setAspects(reviewAttendeesAspects);
			}
			
			if (name.equals ("attendee") && depth.get(1).equals ("attendee") && depth.size() == 2) {
				reviewAttendees.add(currentAttendee);
				currentAttendee = null;
			}
			
			if (name.equals ("aspect") && depth.get(1).equals ("aspect") && depth.size() == 2) {
				if (!reviewAspects.hasId(currentAspect.getId())) {
					reviewAspects.add(currentAspect);
				}
				currentAspect = null;
			}
			
			if (name.equals ("meeting") && depth.get(1).equals ("meeting") && depth.size() == 2) {
				reviewMeetings.add(currentMeeting);
				currentMeeting = null;
			}
			
			if (name.equals ("protocol") && depth.get(1).equals ("meeting") && depth.get(2).equals ("protocol") && depth.size() == 3) {
				currentProtocol.setFindings(reviewMeetingProtocolFindings);
				currentProtocol.setAvailableAttendees(availableAttendees);
				reviewMeetingProtocolFindings = null;
				currentMeeting.setProtocol(currentProtocol);
				currentProtocol = null;
				availableAttendees = null;
			}
			
			if (name.equals ("finding") && depth.get(1).equals ("meeting") && depth.get(2).equals ("protocol") && depth.get(3).equals ("finding") && depth.size() == 4) {
				currentFinding.setReferences(reviewMeetingProtocolFindingReferences);
				
				List<URI>externRefs = new ArrayList<URI>();
				for(String str: reviewMeetingProtocolFindingExternalReferences) {
					URI uriRef;
					try {
						uriRef = new URI(str);
						externRefs.add(uriRef);
					} catch (URISyntaxException e) {
						// never throws, because file was checked by validator
					}
				}
				currentFinding.setExternalReferences(externRefs);
				currentFinding.setAspects(reviewMeetingProtocolFindingAspects);
				reviewMeetingProtocolFindings.add(currentFinding);
				currentFinding = null;
			}
			
			if (name.equals ("attendee") && depth.get(1).equals ("meeting") && depth.get(2).equals ("protocol") && depth.get(3).equals ("attendee") && depth.size() == 4) {
				availableAttendees.add(currentAvailableAttendee);
			}
			

			//end work
			if (depth.contains(name)) {
				depth.pop();
			}
			
			currentElementState = CLOSED;
	    }
		
		@Override
		public void characters(char[] chars, int start, int end)
				throws SAXException {
			
			String text = new String(chars, start, end).trim();
			
			if (currentElementState == OPENED && currentElement != null)  {
				XMLGregorianCalendar xmlCalendar;
				
				switch (currentElement) {
					case REVIEW: 
						//review = new Review();
						break;
					
					case REVIEW_NAME: 
						review.setName(text);
						break;
					
					case REVIEW_DESCRIPTION: 
						review.setDescription(text);
						break;
					
					case REVIEW_PRODUCT: 
						//review.setProduct(new Product());
						break;
						
					case REVIEW_PRODUCT_NAME: 
						review.getProduct().setName(text);
						break;
						
					case REVIEW_PRODUCT_REFERENCE: 
						reviewProductReference.add(text);
						break;
					
					case REVIEW_PRODUCT_VERSION: 
						review.getProduct().setVersion(text);
						break;
					
					case REVIEW_ATTENDEE: 
						//currentAttendee = new Attendee();
						break;
						
					case REVIEW_ATTENDEE_ID:
						currentAttendee.setId(text);
						break;
						
					case REVIEW_ATTENDEE_NAME: 
						currentAttendee.setName(text);
						break;
						
					case REVIEW_ATTENDEE_CONTACT: 
						currentAttendee.setContact(text);
						break;
						
					case REVIEW_ATTENDEE_ROLE: 
						if (text.equals("moderator")) {
							currentAttendee.setRole(AttendeeRole.Moderator);
						} else if (text.equals("scribe")) {
							currentAttendee.setRole(AttendeeRole.Scribe);
						} else if (text.equals("reviewer")) {
							currentAttendee.setRole(AttendeeRole.Reviewer);						
						} else if (text.equals("author")) {
							currentAttendee.setRole(AttendeeRole.Author);
						} else if (text.equals("customer")) {
							currentAttendee.setRole(AttendeeRole.Customer);
						}
						break;
						
					case REVIEW_ATTENDEE_ASPECTS: 
						//reviewAttendeesAspects = new IdArrayList<Aspect>();
						break;
					
					case REVIEW_ATTENDEE_ASPECTS_ASPECT$ID: 
						Aspect aspect = new Aspect();
						aspect.setId(text);
						reviewAttendeesAspects.add(aspect);
						break;
					
					case REVIEW_ASPECT: 
						//currentAspect = new Aspect();
						break;
						
					case REVIEW_ASPECT_ID: 
						currentAspect.setId(text);
						break;
						
					case REVIEW_ASPECT_CATEGORY: 
						currentAspect.setCategory(text);
						break;
						
					case REVIEW_ASPECT_DIRECTIVE: 
						currentAspect.setDirective(text);
						break;
						
					case REVIEW_ASPECT_DESCRIPTION: 
						currentAspect.setDescription(text);
						break;
					
					case REVIEW_SEVERETIES: 
						break;
						
					case REVIEW_SEVERETIES_SEVERITY: 
						reviewSeverities.add(new Severity(text));
						break;
					
					case REVIEW_MEETING: 
						//currentMeeting = new Meeting();
						break;
					
					case REVIEW_MEETING_PLANNED$DATE:
						xmlCalendar = dataType.newXMLGregorianCalendar(text);
						currentMeeting.setPlannedDate(
								xmlCalendar.toGregorianCalendar());
						break;
					
					case REVIEW_MEETING_PLANNED$START:
						xmlCalendar = dataType.newXMLGregorianCalendar(text);
						currentMeeting.setPlannedStart(
								xmlCalendar.toGregorianCalendar());
						break;
						
					case REVIEW_MEETING_PLANNED$END:
						xmlCalendar = dataType.newXMLGregorianCalendar(text);
						currentMeeting.setPlannedEnd(
								xmlCalendar.toGregorianCalendar());
						break;
						
					case REVIEW_MEETING_PLANNED$LOCATION:
						currentMeeting.setPlannedLocation(text);
						break;
						
					case REVIEW_MEETING_CANCELED: 
						currentMeeting.setCanceled(text);
						break;
					
					case REVIEW_MEETING_COMMENTS: 
						currentMeeting.setComments(text);
						break;
					
					case REVIEW_MEETING_PROTOCOL: 
						//currentProtocol = new Protocol();
						//reviewMeetingProtocolFindings = new IdArrayList<Finding>();
						//availableAttendees = new IdArrayList<AvailableAttendee>();
						break;
						
					case REVIEW_MEETING_PROTOCOL_DATE: 
						xmlCalendar = dataType.newXMLGregorianCalendar(text);
						currentProtocol.setDate(
								xmlCalendar.toGregorianCalendar());
						break;
					
					case REVIEW_MEETING_PROTOCOL_START: 
						xmlCalendar = dataType.newXMLGregorianCalendar(text);
						currentProtocol.setStart(
								xmlCalendar.toGregorianCalendar());
						break;
					
					case REVIEW_MEETING_PROTOCOL_END: 
						xmlCalendar = dataType.newXMLGregorianCalendar(text);
						currentProtocol.setEnd(
								xmlCalendar.toGregorianCalendar());
						break;
					
					case REVIEW_MEETING_PROTOCOL_LOCATION:
						currentProtocol.setLocation(text);
						break;
					
					case REVIEW_MEETING_PROTOCOL_COMMENTS: 
						currentProtocol.setComments(text);
						break;
					
					case REVIEW_MEETING_PROTOCOL_ATTENDEE: 
						//currentAvailableAttendee = new AvailableAttendee(new Attendee());
						break;
					
					case REVIEW_MEETING_PROTOCOL_ATTENDEE_ATTENDEE: 
						currentAvailableAttendee.setId(text);
						break;
					
					case REVIEW_MEETING_PROTOCOL_ATTENDEE_PREPARATION$TIME: 
						Duration xmlDuration = dataType.newDuration(text);
						currentAvailableAttendee.setPreparationTime(
								xmlDuration.getTimeInMillis(new GregorianCalendar(1970, 1, 1)));
						break;
					
					case REVIEW_MEETING_PROTOCOL_FINDING: 
						//currentFinding = new Finding();
						//reviewMeetingProtocolFindingReferences = new ArrayList<String>();
						//reviewMeetingProtocolFindingAspects = new ArrayList<String>();
						break;
						
					case REVIEW_MEETING_PROTOCOL_FINDING_ID: 
						currentFinding.setId(text);
						break;
					
					case REVIEW_MEETING_PROTOCOL_FINDING_SEVERITY: 
						currentFinding.setSeverity(new Severity(text));
						break;
						
					case REVIEW_MEETING_PROTOCOL_FINDING_DESCRIPTION: 
						currentFinding.setDescription(text);
						break;
					
					case REVIEW_MEETING_PROTOCOL_FINDING_REFERENCE:
						reviewMeetingProtocolFindingReferences.add(text);
						break;
						
					case REVIEW_MEETING_PROTOCOL_FINDING_EXTERNAL$REFERENCE:
						reviewMeetingProtocolFindingExternalReferences.add(text);
						break;
					
					case REVIEW_MEETING_PROTOCOL_FINDING_ASPECT: 
						reviewMeetingProtocolFindingAspects.add(text);
						break;
					
					case REVIEW_IMPRESSION: 
						review.setImpression(text);
						break;
					
					case REVIEW_RECOMMENDATION: 
						review.setRecommendation(text);
						break;
					
					case REVIEW_COMMENTS: 
						review.setComments(text);
						break;
				}
			}
		}
	}

}